package com.cccyy.encry;

import cn.hutool.core.util.HexUtil;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;

import java.util.Base64;

public class Sm2PubKeyUnZip {
    public static void main(String[] args) {
//        EncryptUtil.generateSM2KeyPair();

        // 假设这是你的SM2密钥的16进制字符串
//        String hexString = "0336620abe155ef2ecdf100f479aaed553a804c1fcdccc9c89b89ca770e7415c03"; //AzZiCr4VXvLs3xAPR5qu1VOoBMH83Mycibicp3DnQVwD
//        extracted(hexString);

        String compressedPublicKey = "0336620abe155ef2ecdf100f479aaed553a804c1fcdccc9c89b89ca770e7415c03";
        getBase64Info(compressedPublicKey); //未压缩公钥：0436620abe155ef2ecdf100f479aaed553a804c1fcdccc9c89b89ca770e7415c034b022b77c570cf96eb55d9bde4e9cb29ac1cac09b93acdd7dc142a261aec2269

//        String compressedPublicKey = "0336620abe155ef2ecdf100f479aaed553a804c1fcdccc9c89b89ca770e7415c03";

        // 还原压缩公钥为非压缩格式
//        ECPublicKeyParameters publicKeyParameters = decompressPublicKey(compressedPublicKey);
//
//        // 将非压缩公钥转换为字节数组
//        byte[] publicKeyBytes = publicKeyParameters.getQ().getEncoded(false);
//
//        // 将字节数组编码为Base64字符串
//        String base64PublicKey = Base64.getEncoder().encodeToString(publicKeyBytes);
//
//        System.out.println("Base64编码后的非压缩公钥: " + base64PublicKey);
    }

    //解压缩公钥
    public static void getBase64Info(String compressedPublicKey) {
//        String compressedPublicKey = "02 或 03 开头的压缩公钥";
        // 获取一条SM2曲线参数
        X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
        // 构造ECC算法参数，曲线方程、椭圆曲线G点、大整数N
        ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
        //提取公钥点
        ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(Hex.decode(compressedPublicKey));
        // 公钥前面的02或者03表示是压缩公钥，04表示未压缩公钥, 04的时候，可以去掉前面的04
        ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);
        String uncompressedPublicKey = HexUtil.encodeHexStr(publicKeyParameters.getQ().getEncoded(false));
        System.out.println("未压缩公钥：" + uncompressedPublicKey);
    }

    // 还原压缩公钥的辅助方法
    public static ECPublicKeyParameters decompressPublicKey(String compressedPublicKey) {
        // 获取SM2曲线参数
        X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
        ECDomainParameters domainParameters = new ECDomainParameters(
                sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN()
        );

        // 提取公钥点
        ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(Hex.decode(compressedPublicKey));

        // 构造ECPublicKeyParameters对象
        return new ECPublicKeyParameters(pukPoint, domainParameters);
    }


    private static void extracted(String hexString) {
        // 将16进制字符串转换为字节数组
        byte[] byteArray = hexStringToByteArray(hexString);

        // 将字节数组编码为Base64字符串
        String base64String = Base64.getEncoder().encodeToString(byteArray);

        System.out.println("Base64编码后的字符串: " + base64String);
    }

    // 将16进制字符串转换为字节数组的辅助方法
    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i + 1), 16));
        }
        return data;
    }
}
